package com.ruoyi.business.controller.system;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.business.domain.*;
import com.ruoyi.business.service.*;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.config.WxAppConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.AppUser;
import com.ruoyi.common.core.domain.model.LoginAppBody;
import com.ruoyi.common.core.domain.model.LoginAppUser;
import com.ruoyi.common.core.domain.model.WxLoginBody;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.exception.job.TaskException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.framework.config.ServerConfig;
import com.ruoyi.framework.web.service.AppLoginService;
import com.ruoyi.framework.web.service.AppTokenService;
import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.service.ISysJobService;
import com.ruoyi.quartz.util.CronUtils;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.IAppUserService;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysNoticeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.formula.functions.T;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 登录验证
 *
 * @author ruoyi
 */
@Api(tags = "APP登录管理")
@RestController
@RequestMapping("/app")
public class AppLoginController extends BaseController {
    @Autowired
    private ServerConfig serverConfig;
    @Autowired
    WxAppConfig wxAppConfig;

    @Autowired
    RestTemplate restTemplate;

    @Resource
    AppTokenService appTokenService;

    @Resource
    private AppLoginService appLoginService;

    @Resource
    private IAppUserService iAppUserService;

    @Resource
    private ICourseService iCourseService;

    @Resource
    private ICourseOrdersService iCourseOrdersService;

    @Resource
    private ICoachService iCoachService;

    @Resource
    private IFeedbackService iFeedbackService;

    @Resource
    private IMemberService iMemberService;

    @Resource
    private ISysNoticeService iSysNoticeService;

    @Resource
    private ISysDictDataService iSysDictDataService;

    @Resource
    private ISysJobService iSysJobService;

    @Resource
    private IMemberCardService iMemberCardService;

    @ApiOperation("登录")
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginAppBody loginAppBody) {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = appLoginService.login(loginAppBody.getUsername(), loginAppBody.getPassword());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    @ApiOperation("移动端上传")
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) throws Exception {
        try {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;
            //todo
//            AjaxResult ajax = AjaxResult.success();
            JSONObject data = new JSONObject();
            data.put("url", url);
            data.put("fileName", fileName);
            data.put("newFileName", FileUtils.getName(fileName));
            data.put("originalFilename", file.getOriginalFilename());
            return AjaxResult.success(data);
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    @ApiOperation("微信小程序登录")
    @PostMapping("/wxLogin")
    public AjaxResult wxLogin(@RequestBody WxLoginBody wxLoginBody) {
        WechatUtils wechatUtils = new WechatUtils();
        String code = wxLoginBody.getCode();
        //秘钥
        String encryptedIv = wxLoginBody.getEncryptedIv();
        //加密数据
        String encryptedData = wxLoginBody.getEncryptedData();
        JSONObject decryptResult;
        try {

            //假如没有绑定微信敞开渠道，解析结果是没有unionid的。
            decryptResult = wechatUtils.getPhoneNumberJson(code, encryptedIv, encryptedData, wxAppConfig.getAppId(), wxAppConfig.getAppSecret());
            System.out.println("解密结果" + decryptResult.toString());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("微信登录失败！");
        }
        if (!decryptResult.isEmpty()) {
            //假如解析成功,获取token
            String token = getWxLoginToken(decryptResult);
            System.out.println("token" + token);
            AjaxResult ajax = AjaxResult.success();
            Map resultMap = new HashMap<>();
            resultMap.put(Constants.TOKEN, token);
            ajax.put("data", resultMap);
            return ajax;
        } else {
            return AjaxResult.error("微信登录失利！");
        }
    }

    @ApiOperation("根据token获取用户信息")
    @GetMapping("/userInfo")
    public AjaxResult userInfo() {
        AppUser appUser = getLoginAppUser().getAppUser();
        AppUser newAppUser = iAppUserService.selectAppUserById(appUser.getUserId());
        if (newAppUser == null) {
            return AjaxResult.error(401, "用户不存在，请重新登陆");
        }
        System.out.println("用户信息：" + newAppUser.toString());
        AjaxResult ajax = AjaxResult.success();
        ajax.put("data", newAppUser);
        return ajax;
    }

    @ApiOperation("修改用户信息")
    @PostMapping("/updateUserInfo")
    public AjaxResult changeUser(@RequestBody AppUser appUser) {
        if (!Objects.equals(appUser.getNickName(), "")) {
            CourseOrders courseOrders = new CourseOrders();
            courseOrders.setId(appUser.getUserId());
            List<CourseOrders> courseOrdersList = iCourseOrdersService.getCourseOrdersList(courseOrders);
            for (CourseOrders courseOrders1 : courseOrdersList) {
                courseOrders1.setUserName(appUser.getNickName());
                iCourseOrdersService.updateCourseOrders(courseOrders);
            }
        }
        // 由于登录后获取用户信息取得是缓存所以，需要修改下缓存
        LoginAppUser loginAppUser = new LoginAppUser();
        AppUser appUser1 = getLoginAppUser().getAppUser();
        appUser1.setNickName(appUser.getNickName());
        loginAppUser.setAppUser(appUser1);
        appTokenService.refreshToken(loginAppUser);
        iAppUserService.updateAppUser(appUser);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("data", "修改用户成功");
        return ajax;
    }

    @ApiOperation("移动端获取课程详情")
    @GetMapping("/courseDetail")
    public AjaxResult getCourseDetail(@RequestParam Long id) {
        Course course = iCourseService.getCourseById(id);
        if (course.getCoachId() != null) {
            Coach coach = iCoachService.getCoachById(course.getCoachId());
            course.setCoachList(coach);
        }
        return success(course);
    }

    @ApiOperation("移动端根据教练id获取课程列表")
    @GetMapping("/getCourseByCoachId")
    public TableDataInfo getCourseByCoachId(Course course) {
        List<Course> courseList = iCourseService.getCourseListByCoachId(course);
        return getDataTable(courseList);
    }

    @ApiOperation("移动端根据教练id和日期获取课程列表")
    @GetMapping("/getCourseByCoachIdAndTime")
    public AjaxResult getCourseByCoachIdAndTime(Course course) {
        List<Course> courseList = iCourseService.getCourseListByCoachIdAndTime(course);
        return success(courseList);
    }

    @ApiOperation("移动端根据状态获取预约订单列表")
    @GetMapping("/getOrdersByStatus")
    public TableDataInfo getOrdersByStatus(CourseOrders courseOrders) {
        List<CourseOrders> courseOrdersList = iCourseOrdersService.getCourseOrdersListByStatus(courseOrders);
        for (CourseOrders courseOrders1 : courseOrdersList) {
            Course course = iCourseService.getCourseById(courseOrders1.getCourseId());
            if (course == null) {
                continue;
            }
            courseOrders1.setCourseList(course);
        }
        return getDataTable(courseOrdersList);
    }

    @ApiOperation("移动端根据类型获取预约订单列表")
    @GetMapping("/getOrdersByType")
    public TableDataInfo getOrdersByType(CourseOrders courseOrders) {
        List<CourseOrders> courseOrdersList = iCourseOrdersService.getCourseOrdersListByType(courseOrders);
        return getDataTable(courseOrdersList);
    }

    @ApiOperation("移动端根据用户获取会员卡信息")
    @PostMapping("/getMemberList")
    public AjaxResult getMemberList(@RequestBody CourseOrders courseOrders) {
        AppUser appUser = getLoginAppUser().getAppUser();
        AppUser newAppUser = iAppUserService.selectAppUserById(appUser.getUserId());
        Course course = iCourseService.getCourseById(courseOrders.getCourseId());
        Member member = new Member();
        member.setUserId(newAppUser.getUserId());
        member.setCourseType(course.getType());
        List<Member> oneMemberList = iMemberService.selectMemberListByTypeAndTime(member);
        List<Member> twoMemberList = iMemberService.selectMemberListByTypeAndStatus(member);
        List<Member> otherMemberList = iMemberService.selectMemberListByTypeAndNumber(member);
        List<Member> allMemberList = new ArrayList<>();
        allMemberList.addAll(oneMemberList);
        allMemberList.addAll(twoMemberList);
        allMemberList.addAll(otherMemberList);
        return success(allMemberList);
    }

    @PostMapping("/orderCourse")
    @ApiOperation(value = "课程预约")
    public AjaxResult orderCourse(@RequestBody CourseOrders courseOrders) throws ParseException, SchedulerException, TaskException {
        AppUser appUser = getLoginAppUser().getAppUser();
        System.out.println("预约客户信息：姓名：" + appUser.getNickName() + ",手机号：" + appUser.getMobile() + ",id:" + appUser.getUserId());
        if (courseOrders.getCourseId() == null) {
            return error("请先选择课程");
        }
        if (courseOrders.getMemberId() == null) {
            return error("请先选择卡券");
        }
        AppUser newAppUser = iAppUserService.selectAppUserById(appUser.getUserId());
        Course course = iCourseService.getCourseById(courseOrders.getCourseId());
        String[] times = course.getTimeSlot().split(",");
        String startTimeStr = course.getStartDate() + " " + times[0] + ":00";
        if (!DateUtils.compareDateTime(DateUtils.getTime(), DateUtils.minusOrPlusMinutesToString(startTimeStr, -course.getOffset())).equals("before")) {
            return error("当前已过预约时间，无法预约哦！");
        }
        Member member = iMemberService.selectMemberById(courseOrders.getMemberId());
//        member.setUserId(newAppUser.getUserId());
//        member.setCourseType(course.getType());
//        List<Member> oneMemberList = iMemberService.selectMemberListByTypeAndTime(member);
//        List<Member> otherMemberList = iMemberService.selectMemberListByTypeAndNumber(member);
        System.out.println("会员信息：" + member.toString());
//        if (Objects.equals(course.getType(), "0")) {
//            if (oneMemberList.isEmpty() && otherMemberList.isEmpty()) {
//                return error("您不是会员也没有购买该课程,需要成为会员或购买该课程才能预约哦！");
//            }
////            if (!oneMemberList.isEmpty()) {
////                String startTime = courseOrders.getStartTime().split(" ")[0];
////                CourseOrders courseOrders1 = new CourseOrders();
////                courseOrders1.setStartTime(startTime);
////                courseOrders1.setUserId(appUser.getUserId());
////                System.out.println("开始时间：" + startTime);
////                List<CourseOrders> courseOrdersList = iCourseOrdersService.selectCourseOrderByTime(courseOrders1);
////                System.out.println("课程数据：" + courseOrdersList);
////                if (!courseOrdersList.isEmpty()) {
////                    return error("您今天已经预约过课程了，请不要重复预约");
////                }
////            }
//        } else {
//            if (otherMemberList.isEmpty()) {
//                return error("您没有购买该课程，需要购买后才能预约哦");
//            }
//        }
        if (Objects.equals(course.getType(), "3") && (courseOrders.getTimes() == null || courseOrders.getTimes().isEmpty())) {
            return error("请选择预约时间");
        }
        if (!course.getCurrentNum().equals(course.getEnrollments())) { // 判断是否是排队预约
            Long number = course.getCurrentNum();
            if (number + courseOrders.getNumber() > course.getEnrollments()) {
                return error("不能超过可预约数量");
            }
            Long newNumber = number + courseOrders.getNumber();
            System.out.println("新数据：" + newNumber);

            if (course.getOrderIds() != null && !course.getOrderIds().isEmpty()) {
                String[] ids = course.getOrderIds().split(",");
                if (Arrays.asList(ids).contains(Long.toString(appUser.getUserId()))) {
                    return error("您已经预约过了！");
                } else {
                    course.setOrderIds(course.getOrderIds() + ',' + appUser.getUserId());
                }
            } else {
                course.setOrderIds(Long.toString(appUser.getUserId()));
            }
        } else { // 排队预约
            Long queueNum = course.getQueueAppointmentNum() + 1;
            if (queueNum > course.getWaitNumber()) {
                return error("不能超过可预约排队数量");
            }
            course.setQueueAppointmentNum(queueNum);
            if (course.getWaitIds() != null) {
                String[] ids = course.getWaitIds().split(",");
                if (Arrays.asList(ids).contains(Long.toString(appUser.getUserId()))) {
                    return error("您已经在排队了！");
                } else {
                    course.setWaitIds(course.getWaitIds() + ',' + appUser.getUserId());
                }
            } else {
                course.setWaitIds(Long.toString(appUser.getUserId()));
            }
        }
        if (Objects.equals(member.getType(), "1")) {
            if (courseOrders.getNumber() + member.getUseNumber() > member.getOrderNumber()) {
                return error("您预约的数量超过您可预约的数量，请重新选择");
            }
            member.setUseNumber(courseOrders.getNumber() + member.getUseNumber());
            if (Objects.equals(member.getOrderNumber(), member.getUseNumber())) {
                member.setStatus("2");
            }
            iMemberService.updateMember(member);
        }
//        if (oneMemberList.isEmpty() && !otherMemberList.isEmpty()) {
//            Member member1 = otherMemberList.get(0);
//            if (courseOrders.getNumber() + member1.getUseNumber() > member1.getOrderNumber()) {
//                return error("您预约的数量超过您可预约的数量，请重新选择");
//            }
//            member1.setUseNumber(courseOrders.getNumber() + member1.getUseNumber());
//            if (Objects.equals(member1.getOrderNumber(), member1.getUseNumber())) {
//                member1.setStatus("2");
//            }
//            iMemberService.updateMember(member1);
//        }
        if (Objects.equals(member.getType(), "0") && member.getUseStartTime() == null) {
            Date currentDate = new Date();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(currentDate);
            calendar.add(Calendar.DAY_OF_YEAR, Math.toIntExact(member.getMemberDuration()));
            Date newDate = calendar.getTime();
            member.setUseStartTime(currentDate);
            member.setUseEndTime(newDate);
            member.setStatus("1");
            System.out.println("开始时间：" + currentDate);
            System.out.println("结束时间：" + newDate);
            iMemberService.updateMember(member);
        }
        courseOrders.setUserId(appUser.getUserId());
        courseOrders.setCourseName(course.getName());
        courseOrders.setUserName(newAppUser.getNickName());
        System.out.println("订单信息：" + courseOrders.toString());
        // 新增预约订单
        iCourseOrdersService.insertCourseOrders(courseOrders);
        Long id = courseOrders.getId();
        System.out.println("新增的订单：" + courseOrders.toString());
        DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String startCron = CronUtils.getCron(format.parse(courseOrders.getStartTime() + ":00"));
        String endCron = CronUtils.getCron(format.parse(courseOrders.getEndTime() + ":00"));
        Long startJobId = iSysJobService.insertOrderJob("课程【" + course.getName() + "】开始任务", "DEFAULT", id, "1", startCron);
        Long endJobId = iSysJobService.insertOrderJob("课程【" + course.getName() + "】结束任务", "DEFAULT", id, "2", endCron);
        StringJoiner joiner = new StringJoiner(",");
        joiner.add(startJobId.toString());
        joiner.add(endJobId.toString());
        courseOrders.setJobIds(joiner.toString());
        System.out.println("更新订单所对应的任务id:" + joiner.toString());
        iCourseOrdersService.updateCourseOrders(courseOrders);
        // 更新课程数据
        course.setCurrentNum(course.getCurrentNum() + courseOrders.getNumber());
        iCourseService.updateCourse(course);
        return success(courseOrders);
    }

    @GetMapping("/cancelOrders")
    @ApiOperation(value = "预约课程取消")
    public AjaxResult cancelOrders(@RequestParam Long id) {
        AppUser appUser = getLoginAppUser().getAppUser();
        AppUser newAppUser = iAppUserService.selectAppUserById(appUser.getUserId());
        // 先获取订单信息
        CourseOrders courseOrders = iCourseOrdersService.getCourseOrdersById(id);
        Member member = iMemberService.selectMemberById(courseOrders.getMemberId());
        System.out.println("订单：" + courseOrders.toString());
        if (!Objects.equals(courseOrders.getStatus(), "0")) {
            String str = Objects.equals(courseOrders.getStatus(), "1") ? "开始" : Objects.equals(courseOrders.getStatus(), "2") ? "结束" : "取消";
            return error("订单已经" + str + "，不能取消");
        }
        // 获取课程
        Course course = iCourseService.getCourseById(courseOrders.getCourseId());
        // 减少课程预约数
        course.setCurrentNum(course.getCurrentNum() - courseOrders.getNumber());
        course.setOrderIds(ToolUtils.RemoveTargetForString(course.getOrderIds(), courseOrders.getUserId()));
        iCourseService.updateCourse(course);
        courseOrders.setStatus("3");
        courseOrders.getParams().put("setMemberIdNull", true);
        if (courseOrders.getJobIds() != null) {
            String[] jobIds = courseOrders.getJobIds().split(",");
            Long[] longArray = new Long[jobIds.length];
            for (int i = 0; i < jobIds.length; i++) {
                longArray[i] = Long.parseLong(jobIds[i]);
            }
            try {
                iSysJobService.deleteJobByIds(longArray);
            } catch (SchedulerException e) {
                throw new RuntimeException(e);
            }
        }
        iCourseOrdersService.updateCourseOrders(courseOrders);
        if (member != null) {
            if (Objects.equals(member.getType(), "1")) {
                member.setUseNumber(member.getUseNumber() - courseOrders.getNumber());
                if (Objects.equals(member.getStatus(), "2") && member.getUseNumber() <= member.getOrderNumber()) {
                    member.setStatus("1");
                }
                iMemberService.updateMember(member);
            } else {
                CourseOrders courseOrders1 = new CourseOrders();
                courseOrders1.setUserId(newAppUser.getUserId());
                courseOrders1.setMemberId(member.getId());
                System.out.println("取消会员订单信息：" + courseOrders1.toString());
                List<CourseOrders> courseOrdersList = iCourseOrdersService.selectCourseOrdersByUserId(courseOrders1);
                System.out.println("订单列表" + courseOrdersList.toString());
                if (courseOrdersList.isEmpty()) {
                    member.setStatus("0");
                    member.getParams().put("setUseStartTimeNull", true);
                    member.getParams().put("setUseEndTimeNull", true);
                    iMemberService.updateMember(member);
                }
            }
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("data", "取消预约课程成功");
        return ajax;
    }

    @ApiOperation(value = "发送意见反馈")
    @PostMapping("/feedback/insert")
    public AjaxResult insertFeedback(@RequestBody Feedback feedback) {
        AppUser appUser = getLoginAppUser().getAppUser();
        AppUser newAppUser = iAppUserService.selectAppUserById(appUser.getUserId());
        System.out.println("发送人：" + newAppUser.getNickName());
        feedback.setPresenter(newAppUser.getNickName());
        feedback.setCreateBy(newAppUser.getUserName());
        iFeedbackService.insertFeedback(feedback);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("data", "发送意见反馈成功");
        return ajax;
    }

    @ApiOperation(value = "获取用户的充值记录")
    @GetMapping("/getMembersByUserId")
    private AjaxResult getMembersByUserId() {
        AppUser appUser = getLoginAppUser().getAppUser();
        List<Member> members = iMemberService.selectMemberListByUserId(appUser.getUserId());
        for (Member member : members) {
            if (Objects.equals(member.getType(), "0")) {
                MemberCard memberCard = iMemberCardService.getMemberCardById(Long.valueOf(member.getMemberType()));
                member.setMemberName(memberCard.getName());
            }
        }
        return success(members);
    }


    private String getWxLoginToken(JSONObject jsonObject) {
        System.out.println(jsonObject);
        //获取nickName
        String nickName = RandomUtils.generateRandomChinese(3);// 生成16位随机昵称
        //还可以获取其他信息
        //依据openid判别数据库中是否有该用户
        //依据openid查询用户信息
        AppUser wxUser = iAppUserService.selectAppUserByMobile(jsonObject.getString("phoneNumber"));
        //假如查不到，则新增，查到了，则更新
        AppUser appUser = new AppUser();
        if (wxUser == null) {
            // 新增
            appUser.setNickName(nickName);
            appUser.setUserName(jsonObject.getString("phoneNumber"));
            appUser.setMobile(jsonObject.getString("phoneNumber"));
            appUser.setPassword(SecurityUtils.encryptPassword("123456"));
            appUser.setOpenId(jsonObject.getString("openId"));
            iAppUserService.insertAppUser(appUser);
        } else {
            appUser = wxUser;
            if (appUser.getOpenId() == null || appUser.getOpenId().isEmpty()) {
                appUser.setOpenId(jsonObject.getString("openId"));
                iAppUserService.updateAppUser(appUser);
            }
        }
        LoginAppUser loginAppUser = new LoginAppUser();
        loginAppUser.setAppUser(appUser);
        return appTokenService.createAppToken(loginAppUser);
    }
}